package com.candy.databasedocuments.service.document;

import com.aspose.words.*;
import com.candy.databasedocuments.entity.Table;
import com.candy.databasedocuments.enums.DocumentEnum;
import com.candy.databasedocuments.service.AbstractDocumentService;
import com.candy.databasedocuments.utils.ApplicationContentUtils;
import com.candy.databasedocuments.utils.ToolsUtils;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import org.docx4j.Docx4J;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.List;

/**
 * @author suYanLong
 * @version 1.0
 * @date 2023/7/7 11:11
 * @Description pdf文档
 */
@Component
public class PdfDocumentServiceImpl extends AbstractDocumentService {

    static Logger log = LoggerFactory.getLogger(PdfDocumentServiceImpl.class);

    @Override
    public String tableToDocument(List<Table> tableList) throws Exception {
        // 先生产word文档，将 word -> pdf
        AbstractDocumentService abstractDocumentService = (AbstractDocumentService) ApplicationContentUtils.getBean(DocumentEnum.WORD.getDocumentServiceImpl());
        String sourcePath = abstractDocumentService.tableToDocument(tableList);
        String targetPath = databaseConfig.getDcAttr().getPath() + ToolsUtils.getFileName("pdf");
        asposeWordToPdf(sourcePath, targetPath);
        return targetPath;
    }

    public static void main(String[] args) throws IOException {
        String sourcePath = "C:\\Users\\Administrator\\Desktop\\2023-07-19_01-21-112.docx";
        String targetPath = "C:\\Users\\Administrator\\Desktop\\2023-07-18_05-31-126.pdf";
/*
        // TODO 转换失败
        FileInputStream fileInputStream = new FileInputStream(sourcePath);
        XWPFDocument xwpfDocument = new XWPFDocument(fileInputStream);
        PdfOptions pdfOptions = PdfOptions.create();
        FileOutputStream fileOutputStream = new FileOutputStream(targetPath);
        PdfConverter.getInstance().convert(xwpfDocument, fileOutputStream, pdfOptions);
        fileInputStream.close();
        fileOutputStream.close();*/

/*
        // TODO wt00000011 jar包下载不下来
        //实例化Document类的对象
        Document doc = new Document();
        //加载word
        doc.loadFromFile("word文件地址.docx");
        //保存为PDF格式
        doc.saveToFile("自定义pdf名称.pdf", FileFormat.PDF);*/

        // word转pdf
        // https://blog.csdn.net/ka3p06/article/details/125476270

        // 成功
//        asposeWordToPdf(sourcePath, targetPath);

        // TODO 转换失败
//        docx4jWordToPdf(sourcePath, targetPath);

        // 成功
        documents4jWordToPdf(sourcePath, targetPath);
    }

    public static void asposeWordToPdf(String sourcePath, String targetPath) {
        LoadOptions opts = new LoadOptions();
//        opts.setMswVersion(MsWordVersion.WORD_2016);
        opts.getLanguagePreferences().setDefaultEditingLanguage(EditingLanguage.CHINESE_PRC);
        Document doc = null;
        try {
            doc = new Document(sourcePath, opts);
            ParagraphFormat pf = doc.getStyles().getDefaultParagraphFormat();
            pf.clearFormatting();

            PdfSaveOptions options = new PdfSaveOptions();
            // 文字和图像压缩
            options.setExportDocumentStructure(true);
            options.setTextCompression(PdfTextCompression.FLATE);
            options.setImageCompression(PdfImageCompression.AUTO);
            // 接收修订
            doc.acceptAllRevisions();
            // 去掉批注
            NodeCollection nc = doc.getChildNodes(NodeType.COMMENT, true);
            if (nc != null && nc.getCount() > 0) {
                for (int i = 0; i < nc.getCount(); i++) {
                    log.info("清除批注：{}", nc.get(i).getText());
                    Node comment = nc.get(i);
                    comment.getParentNode().removeChild(comment);
                }
            }
            // 将Word另存为PDF
            doc.save(targetPath, options);
        } catch (Exception e) {
            log.error("[aspose] word转pdf失败:{}", e.toString());
        }

    }

    /**
     * 通过docx4j 实现word转pdf
     *
     * @param sourcePath 源文件地址 如 /root/example.doc
     * @param targetPath 目标文件地址 如 /root/example.pdf
     */
    public static void docx4jWordToPdf(String sourcePath, String targetPath) {
        try {
            WordprocessingMLPackage pkg = Docx4J.load(new File(sourcePath));
            Mapper fontMapper = new IdentityPlusMapper();
            fontMapper.put("隶书", PhysicalFonts.get("LiSu"));
            fontMapper.put("宋体", PhysicalFonts.get("SimSun"));
            fontMapper.put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
            fontMapper.put("黑体", PhysicalFonts.get("SimHei"));
            fontMapper.put("楷体", PhysicalFonts.get("KaiTi"));
            fontMapper.put("新宋体", PhysicalFonts.get("NSimSun"));
            fontMapper.put("华文行楷", PhysicalFonts.get("STXingkai"));
            fontMapper.put("华文仿宋", PhysicalFonts.get("STFangsong"));
            fontMapper.put("仿宋", PhysicalFonts.get("FangSong"));
            fontMapper.put("幼圆", PhysicalFonts.get("YouYuan"));
            fontMapper.put("华文宋体", PhysicalFonts.get("STSong"));
            fontMapper.put("华文中宋", PhysicalFonts.get("STZhongsong"));
            fontMapper.put("等线", PhysicalFonts.get("SimSun"));
            fontMapper.put("等线 Light", PhysicalFonts.get("SimSun"));
            fontMapper.put("华文琥珀", PhysicalFonts.get("STHupo"));
            fontMapper.put("华文隶书", PhysicalFonts.get("STLiti"));
            fontMapper.put("华文新魏", PhysicalFonts.get("STXinwei"));
            fontMapper.put("华文彩云", PhysicalFonts.get("STCaiyun"));
            fontMapper.put("方正姚体", PhysicalFonts.get("FZYaoti"));
            fontMapper.put("方正舒体", PhysicalFonts.get("FZShuTi"));
            fontMapper.put("华文细黑", PhysicalFonts.get("STXihei"));
            fontMapper.put("宋体扩展", PhysicalFonts.get("simsun-extB"));
            fontMapper.put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
            fontMapper.put("新細明體", PhysicalFonts.get("SimSun"));
            pkg.setFontMapper(fontMapper);

            Docx4J.toPDF(pkg, new FileOutputStream(targetPath));
        } catch (Exception e) {
            log.error("[docx4j] word转pdf失败:{}", e.toString());
        }
    }

    /**
     * 通过documents4j 实现word转pdf
     *
     * @param sourcePath 源文件地址 如 /root/example.doc
     * @param targetPath 目标文件地址 如 /root/example.pdf
     */
    public static void documents4jWordToPdf(String sourcePath, String targetPath) {
        File inputWord = new File(sourcePath);
        File outputFile = new File(targetPath);
        try {
            InputStream docxInputStream = new FileInputStream(inputWord);
            OutputStream outputStream = new FileOutputStream(outputFile);
            IConverter converter = LocalConverter.builder().build();
            converter.convert(docxInputStream)
                    .as(DocumentType.DOCX)
                    .to(outputStream)
                    .as(DocumentType.PDF).execute();
            outputStream.close();
        } catch (Exception e) {
            log.error("[documents4J] word转pdf失败:{}", e.toString());
        }
    }

}
